local api = vim.api
local buf, win
local position = 0

-- 当前行的中央插入内容
local function center(str)
  local width = api.nvim_win_get_width(0)
  local shift = math.floor(width / 2) - math.floor(string.len(str) / 2)
  return string.rep(" ", shift) .. str
end

local function open_window()
  buf = api.nvim_create_buf(false, true)

  api.nvim_buf_set_option(buf, "bufhidden", "wipe")
  api.nvim_buf_set_option(buf, "filetype", "uilearn")

  -- 窗口的宽高
  local width = api.nvim_get_option("columns")
  local height = api.nvim_get_option("rows")

  local win_height = math.ceil(height * 0.8 - 4)
  local win_width = math.ceil(width * 0.8)
  local row = math.ceil((height - win_height) / 2 - 1)
  local col = math.ceil((width - win_width) / 2)
  local opts = {
    style = "minimal",
    relative = "editor",
    width = win_width,
    height = win_height,
    row = row,
    col = col,
    border = "rounded",
  }

  -- opts里面已经可以默认创建border了，不需要重新创建了
  win = api.nvim_open_win(buf, true, opts)
  api.nvim_win_set_option(win, "cursorline", true) -- it highlight line with the cursor on it

  -- we can add title already here, because first line will never change
  api.nvim_buf_set_lines(buf, 0, -1, false, { center("What have i done?"), "", "" })
  api.nvim_buf_add_highlight(buf, -1, "WhidHeader", 0, 0, -1)
end

local function update_view(direction)
  api.nvim_buf_set_option(buf, "modifiable", true)
  position = position + direction
  if position < 0 then
    position = 0
  end

  local result = vim.fn.systemlist("git diff-tree --no-commit-id --name-only -r  HEAD~" .. position)
  if #result == 0 then
    table.insert(result, "")
  end -- add  an empty line to preserve layout if there is no results
  for k, v in pairs(result) do
    result[k] = "  " .. result[k]
  end

  api.nvim_buf_set_lines(buf, 1, 2, false, { center("HEAD~" .. position) })
  api.nvim_buf_set_lines(buf, 3, -1, false, result)

  api.nvim_buf_add_highlight(buf, -1, "whidSubHeader", 1, 0, -1)
  api.nvim_buf_set_option(buf, "modifiable", false)
end

local function close_window()
  api.nvim_win_close(win, true)
end

local function open_file()
  local str = api.nvim_get_current_line()
  close_window()
  api.nvim_command("edit " .. str)
end

local function move_cursor()
  local new_pos = math.max(4, api.nvim_win_get_cursor(win)[1] - 1)
  api.nvim_win_set_cursor(win, { new_pos, 0 })
end

local function set_mappings()
  local mappings = {
    ["["] = "update_view(-1)",
    ["]"] = "update_view(1)",
    ["<cr>"] = "open_file()",
    h = "update_view(-1)",
    l = "update_view(1)",
    q = "close_window()",
    k = "move_cursor()",
  }

  for k, v in pairs(mappings) do
    api.nvim_buf_set_keymap(buf, "n", k, ':lua require"whid".' .. v .. "<cr>", {
      nowait = true,
      noremap = true,
      silent = true,
    })
  end
  local other_chars = {
    "a",
    "b",
    "c",
    "d",
    "e",
    "f",
    "g",
    "i",
    "n",
    "o",
    "p",
    "r",
    "s",
    "t",
    "u",
    "v",
    "w",
    "x",
    "y",
    "z",
  }
  for k, v in ipairs(other_chars) do
    api.nvim_buf_set_keymap(buf, "n", v, "", { nowait = true, noremap = true, silent = true })
    api.nvim_buf_set_keymap(buf, "n", v:upper(), "", { nowait = true, noremap = true, silent = true })
    api.nvim_buf_set_keymap(buf, "n", "<c-" .. v .. ">", "", { nowait = true, noremap = true, silent = true })
  end
end

local function whid()
  position = 0
  open_window()
  set_mappings()
  update_view(0)
  api.nvim_win_set_cursor(win, { 4, 0 })
end

return {
  whid = whid,
  update_view = update_view,
  open_file = open_file,
  move_cursor = move_cursor,
  close_window = close_window,
}
